package sample.util;

import sample.stackbak.number.LinkStack;
import sample.stackbak.symbol.Sqstacktp;

import java.util.ArrayList;
import java.util.List;

/**
 * @author czy
 * @create 2021-08-30 9:15
 */
public class Calculation {

    /**
     * 记录后缀表达式的字符,可能出现两位数的计算,使用空格将两个字符(数字及计算符号)分割
     */
    public List<String> list = new ArrayList<>();

    public Object reduced(String string) throws Exception {
        //清空集合,避免影响二次使用
        list.clear();
        char ch, theta;
        double x, y;
        Object result;
        // 运算符栈
        Sqstacktp symbolStack = new Sqstacktp(20);
        // 运算数栈
        LinkStack digitalStack = new LinkStack();
        // 建立运算符
        String tr = "#+-()*/";
        symbolStack.push('#');
        char[] cs = string.toCharArray();
        for (int i = 0; i < cs.length; i++) {
            // 读取字符
            ch = cs[i];
            // 判断是否为运算符
            if (tr.indexOf(ch) == -1) {
                int j = i + 1;
                int n = 0;
                int math = ch - '0';
                while (j < cs.length && tr.indexOf(cs[j]) == -1) {
                    n++;
                    int math1 = cs[j] - '0';
                    math = math * 10 + math1;
                    System.out.println(math);
                    j++;
                    i++;
                }
                // 数字就进入运算数栈
                digitalStack.push(math);
                list.add(math + " ");
                System.out.println(digitalStack);
            }
            // 判断优先级
            else if (ch != ')' && priority(ch, (char) symbolStack.top())) {
                symbolStack.push(ch);
            } else {
                if (ch == ')') {
                    while (!symbolStack.top().equals('(')) {
                        // 弹出栈顶运算符
                        theta = (char) symbolStack.pop();
                        list.add(String.valueOf(theta));
                        // 弹出两个运算数
                        x = (int) digitalStack.pop();
                        y = (int) digitalStack.pop();
                        result = result(y, theta, x);
                        digitalStack.push(result);
                        System.out.println(symbolStack);
                        System.out.println(digitalStack);
                    }
                    list.add(symbolStack.pop().toString());
                } else {
                    // 弹出栈顶运算符
                    theta = (char) symbolStack.pop();
                    list.add(String.valueOf(theta));
                    // 弹出两个运算数
                    x = Double.parseDouble(digitalStack.pop().toString());
                    y = Double.parseDouble(digitalStack.pop().toString());
                    result = result(y, theta, x);
                    digitalStack.push(result);
                    i--;
                }
            }
        }
        while (!symbolStack.top().equals('#')) {
            theta = (char) symbolStack.pop();
            list.add(String.valueOf(theta));
            // 弹出两个运算数
            x = Double.parseDouble(digitalStack.pop().toString());
            y = Double.parseDouble(digitalStack.pop().toString());
            result = result(y, theta, x);
            digitalStack.push(result);
            System.out.println(digitalStack);
        }
        return digitalStack.top();
    }

    private boolean priority(char c1, char c2) {
        String tr = "#+-(*/";
        int i = tr.indexOf(c1);
        int j = tr.indexOf(c2);
        if (i == 3 || j == 0 || j == 3) {
            return true;
        } else if (i > 3 && j < 3) {
            return true;
        } else {
            return false;
        }
    }

    //运算结果
    private Object result(double y, char theta, double x) {
        double result, index;
        String tString = "#+-*/";
        index = tString.indexOf(theta);
        //判断是为乘除加减的一种进行计算
        if (index == 1) {
            result = y + x;
            return result;
        }
        if (index == 2) {
            result = y - x;
            return result;
        }
        if (index == 3) {
            result = y * x;
            return result;
        }
        if (index == 4) {
            result = (double) y / (double) x;
            return result;
        }
        return (Integer) null;
    }
}
